import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
import { Form, Input, message, Popconfirm, Row, Spin } from 'antd';
import { debounce } from 'lodash';

import cn from 'classnames';
import { findParentByClassName } from '@/utils/utils';
import {
    changeQuestionsOrder,
    deleteQuestion,
    saveAnswer,
    saveComment,
    saveQuestion
} from '@/pages/Recruitment/service';
import styles from '@/pages/Recruitment/Interview/Record.less';
import LimitInput from '@/components/LimitInput';
import { Icon } from '@/pages/Recruitment/components';
import RecordTagButton from '@/pages/Recruitment/Interview/Containers/RecordTagButton';
import { DividerContainer } from '@/molecules';
import QuestionRecItem from './components/QuestionRecItem.js'; // 播放录音片段用的组件
import WEBSOCKET_TYPES from '../../utils/WEBSOCKET_TYPES';

// let autoSaveTimmer; // 定时上传问题录音标记用

const SAVE_METHOD_MAPPING = {
    question: saveQuestion,
    answer: saveAnswer,
    comment: saveComment
};

const Toolbar = ({ children }) => {
    const style = { height: 40, marginBottom: 8 };
    return (
        <Row type="flex" align="middle" style={style}>
            {children}
        </Row>
    );
};

const Label = ({ value, colon = false, item }) => {
    const style = { lineHeight: '22px', fontWeight: 500, color: 'rgba(0,0,0,0.65)' };
    return (
        <div style={style} className={value === '评价' && !item?.isEqual ? null : styles.required}>
            {value + (colon ? '：' : '')}
        </div>
    );
};

const firstUpper = word => word.replace(/^\S/, s => s.toUpperCase());

const editFlagName = type => `is${firstUpper(type)}Edit`;
const getPoint = obj => {
    if (!obj) return 0; // 处理没有自定义问题时，添加第一个自定义问题报错。
    let t = obj.offsetTop;
    // eslint-disable-next-line no-cond-assign,no-param-reassign
    while ((obj = obj.offsetParent)) {
        t += obj.offsetTop;
    }
    return t;
};

const answerRules = [
    { required: true, message: '请输入答复!', whitespace: true },
    { max: 2000, message: '答复不能超过2000个字符' }
];

/**
 * 上传前，设置答复为非必填
 */
const allowEmptyAnswer = () => {
    answerRules[0].required = false;
};

const Question = ({
    broadcastUpdateMsg,
    durationMSRef, // 录音时长Ref，毫秒
    wsRef,
    form,
    value = [],
    onChange,
    getRecordState = () => null,
    arrangeId,
    disableButton, // 不显示录音按钮
    scrollWrapRef,
    recData,
    mixedRecordAndUploadState
}) => {
    const [allowAdd, setAllowAdd] = useState(true);
    const [formList, setFormList] = useState([]);
    const formListRef = useRef([]);
    const { getFieldDecorator, validateFields, getFieldValue } = form;
    const [loading, setLoading] = useState(false);
    const questionRef = useRef();
    const answerRef = useRef();
    const commentRef = useRef();
    useEffect(() => {
        setFormList(value);
        formListRef.current = value;
    }, [value]);

    const proxyOnChange = newFormList => {
        onChange(newFormList);
        formListRef.current = newFormList;
    };

    const genUUID = useCallback(
        (length = 14) =>
            Number(
                Math.random()
                    .toString()
                    .substr(3, length) + Date.now()
            ).toString(36),
        []
    );

    const onAddQuestion = () => {
        if (!allowAdd) return;
        setAllowAdd(false);
        const newFormList = getFieldValue('interviewQuestions').slice();
        const newData = {
            isNew: true,
            isEqual: true,
            isQuestionEdit: true,
            isAnswerEdit: true,
            isCommentEdit: true,
            key: genUUID()
        };
        // 插入到自己问题后面
        let index = -1;
        // eslint-disable-next-line no-plusplus
        for (let i = 0; i < newFormList.length; i++) {
            if (!newFormList[i].isEqual) {
                index = i;
                break;
            }
            // 单面试官，无他人问题时，需要处理成往后push
            if (i === newFormList.length - 1) {
                index = newFormList.length;
            }
        }
        if (index === -1) {
            newFormList.unshift(newData);
        } else {
            newFormList.splice(index, 0, newData);
        }
        proxyOnChange(newFormList);
        setTimeout(() => {
            if (scrollWrapRef && scrollWrapRef.current) {
                const obj = findParentByClassName(scrollWrapRef.current, 'tab-scroll-context');
                const item = document.getElementsByClassName('.question-item')[index];
                obj.scrollTop = getPoint(item) - getPoint(obj);
            }
            if (questionRef.current) {
                questionRef.current.focus();
            }
        });
    };

    const forceFormCheck = () => {
        const interviewQuestion = getFieldValue('interviewQuestion').slice();
        form.setFieldsValue({
            // 用于强行让form能够再次检测interviewQuestion
            interviewQuestion: interviewQuestion
                ? interviewQuestion.map(item => ({
                      submitCheck: !item.submitCheck
                  }))
                : []
        });
    };

    /**
     * 向websocket发送事件
     */
    const sendEventToWS = (type, payload = {}) => {
        switch (type) {
            case 'question': // 保存自定义问题
                console.log('操作自定义问题', payload);
                wsRef.current.send({
                    type: WEBSOCKET_TYPES.ADD_QUESTION
                });
                break;
            case 'answer': // 保存输入的答案 or 输入音频
                console.log('保存输入的答案', payload);
                wsRef.current.send({
                    type: WEBSOCKET_TYPES.EDIT_ANSWER,
                    ...payload
                });
                break;
            case 'comment': // 保存输入的评论
                console.log('保存输入的评论', payload);
                break;

            default:
                console.log('WebSocket 无对应事件, type:', type, payload);
                break;
        }
    };

    // 删除自定义问题
    const onDeleteQuestion = async i => {
        const lists = getFieldValue('interviewQuestions');
        const questionId = lists[i].id;
        if (questionId) {
            await deleteQuestion(questionId);
            sendEventToWS('answer', { questionId, answerTimes: lists[i].answerTimes });
            broadcastUpdateMsg(true);
        }
        const newFormList = formList.slice();
        newFormList.splice(i, 1);
        proxyOnChange(newFormList);
        setAllowAdd(true);
    };

    // 编辑/取消编辑
    // 向 WS 发送请求
    const handleToggleEdit = useCallback(
        (index, type) => {
            const newFormList = getFieldValue('interviewQuestions');
            const flagName = editFlagName(type);
            const oldItem = newFormList[index];
            const refs = {
                question: questionRef,
                answer: answerRef,
                comment: commentRef
            };
            newFormList[index] = {
                ...oldItem,
                [flagName]: !oldItem[flagName]
            };
            proxyOnChange(newFormList);
            setTimeout(() => {
                if (refs[type]?.current) {
                    refs[type].current.focus();
                }
            }, 0);
        },
        [onChange, questionRef, answerRef, commentRef]
    );

    /**
     * 保存录音片段到服务器，每间隔5秒
     */
    // const saveQuestionRecToServer = (fieldName, index, type = 'answer', contentName = 'answerContent') => {
    //     const fieldValue = getFieldValue(fieldName);
    //     const newFormList = getFieldValue('interviewQuestions');
    //     const questionId = newFormList[index].id;
    //     const params = { id: newFormList[index][type]?.id, questionId, [contentName]: fieldValue };
    //     // 添加录音片段
    //     const target = newFormList[index];
    //     const answerTimes = cloneDeep(target?.answer?.answerTimes);
    //     // 设置问题录音片段结束时间
    //     const len = answerTimes.length;
    //     answerTimes[len - 1] = {
    //         ...answerTimes[len - 1],
    //         endTime: durationMSRef.current
    //     };
    //     params.answerTimes = answerTimes;
    //     SAVE_METHOD_MAPPING[type]({ arrangeId, ...params }).then(() => {
    //         // 保存操作完成
    //         console.log('录音片段实时保存操作完成:', newFormList[index]);
    //     });
    // };

    /**
     * 保存问题、回答、评论、录音片段标记,到服务器。
     */
    const handleConfirm = useCallback(
        debounce((fieldName, index, type, contentName) => {
            console.log('handleConfirm:', fieldName, index, type, contentName);
            const fieldValue = getFieldValue(fieldName);
            validateFields([fieldName], err => {
                if (!answerRules[0].required) {
                    answerRules[0].required = true; // 录音片段上传后，重新将回答设置为必填
                }
                if (!err) {
                    const newFormList = getFieldValue('interviewQuestions');
                    console.log('handleConfirm', newFormList);
                    const questionId = newFormList[index].id;

                    const params = contentName
                        ? { id: newFormList[index][type]?.id, questionId, [contentName]: fieldValue }
                        : { id: questionId, [type]: fieldValue, orderNo: index + 1 };
                    // 添加录音片段
                    const target = newFormList[index];
                    const answerTimes = target?.answer?.answerTimes;
                    params.answerTimes = answerTimes;

                    setLoading(true);
                    SAVE_METHOD_MAPPING[type]({ arrangeId, ...params }).then(res => {
                        // 保存操作完成
                        console.log('保存操作完成:', newFormList[index]);
                        if (type === 'question') {
                            console.log('==============broadcastUpdateMsg=============> 录音页面');
                            broadcastUpdateMsg(true);
                        }
                        sendEventToWS(type, { questionId, answerTimes: newFormList[index]?.answer?.answerTimes }); // 无论是添加回答，或是添加录音片段，都通过ws发送录音片段
                        setLoading(false);
                        const id = res.data;
                        // 赋值方式区分
                        let nextValue = { [type]: fieldValue, id };

                        // 根据这个判断是不是对象（answer,comment）
                        if (contentName) {
                            nextValue = {
                                [type]: {
                                    ...(newFormList[index][type] || {}),
                                    [contentName]: fieldValue,
                                    id
                                }
                            };
                        }
                        newFormList[index] = {
                            ...newFormList[index],
                            ...nextValue,
                            [editFlagName(type)]: false
                        };

                        proxyOnChange(newFormList);
                        forceFormCheck();
                        setAllowAdd(true);
                    });
                }
            });
        }, 400),
        [onChange]
    );

    // 自定义问题标题 编辑中的状态
    const renderEditingTitle = useCallback(
        (item, index) => (
            <>
                {index + 1}.
                <Form.Item style={{ width: '100%' }}>
                    {getFieldDecorator(`question_${item.id || item.key}`, {
                        initialValue: item.question || '',
                        rules: [
                            { required: true, message: '请输入自定义问题标题!', whitespace: true },
                            { max: 100, message: '自定义问题不能超过100个字符' }
                        ]
                    })(
                        <Input
                            style={{ marginLeft: '10px' }}
                            autoComplete="off"
                            ref={questionRef}
                            onBlur={() => {
                                // if (getFieldError(fieldName)) return;
                                handleConfirm(`question_${item.id || item.key}`, index, 'question');
                            }}
                            onPressEnter={() => {
                                // if (getFieldError(fieldName)) return;
                                handleConfirm(`question_${item.id || item.key}`, index, 'question');
                            }}
                        />
                    )}
                </Form.Item>
            </>
        ),
        []
    );

    // 头部 浏览中
    const renderBrowsingTitle = useCallback((item, index) => {
        const { question, createUserName, isEqual } = item || {};
        return (
            <div className={styles.questionHeaderContent}>
                <div className={styles.questionHeaderTitleWrap}>
                    <span className={styles.orderNo}>{index + 1}.</span>
                    <div
                        className={cn(styles.questionTitleContent, { [styles.questionTitleContentEdit]: isEqual })}
                        onClick={() => {
                            if (isEqual) handleToggleEdit(index, 'question');
                        }}
                    >
                        <span className={styles.questionTitle}>{question}</span>
                        {isEqual && (
                            <i
                                className={cn(
                                    'iconfont',
                                    'iconlistfunction_edit_icon_default',
                                    styles.questionEditIcon
                                )}
                            />
                        )}
                    </div>
                </div>
                <span className={styles.questionCreateWrap}>
                    <i className={cn('iconfont', 'iconPeople_F', styles.createUserIcon)} />
                    <span className={styles.light}>
                        {createUserName || JSON.parse(localStorage.getItem('user')).employeeName}
                    </span>
                </span>
            </div>
        );
    }, []);

    // 头部
    const renderTitle = useCallback(
        (item, index) => {
            if (item[editFlagName('question')]) {
                return renderEditingTitle(item, index);
            }
            return renderBrowsingTitle(item, index);
        },
        [renderEditingTitle, renderBrowsingTitle]
    );

    /**
     * 问题录音片段开始or结束时触发。
     */
    const onQuestionRecord = (item, index) => {
        console.log('onQuestionRecord', item, index);
        const itemIsRecording = item.isRecord; // 用于判断调用时是否在录音
        if (item[editFlagName('question')] || item.loading) return false;
        const newFormList = formListRef.current.slice();
        if (!item.isRecord) {
            newFormList[index] = {
                ...newFormList[index],
                loading: true
            };
            proxyOnChange(newFormList);
            const recordState = getRecordState(); // 获取录音状态
            if ([-1, 0, 2].includes(recordState)) {
                let msg = '';
                if (recordState === 0 || recData.recordUrlState === 1) {
                    msg = '当前录音已结束，不可标记录音时间';
                } else if (recordState === -1) {
                    msg = '当前未开始录音，不可标记录音时间！';
                } else {
                    msg = '当前录音已暂停，不可标记录音时间';
                }
                message.error(msg);
                newFormList[index] = {
                    ...newFormList[index],
                    loading: false
                };
                proxyOnChange(newFormList);
                return false;
            }
        }
        let answerTimes = item.answer && item.answer.answerTimes ? item.answer.answerTimes : [];
        if (item.isRecord) {
            // 设置问题录音片段结束时间
            const len = answerTimes.length;
            answerTimes[len - 1] = {
                ...answerTimes[len - 1],
                endTime: durationMSRef.current
            };
        } else {
            answerTimes.push({
                // 设置问题录音片段开始时间
                startTime: durationMSRef.current
            });
        }
        answerTimes = answerTimes.map((time, i) => ({
            ...time,
            sort: i + 1
        }));
        newFormList[index] = {
            ...newFormList[index],
            answer: {
                ...(newFormList[index].answer || {}),
                answerTimes
            },
            isRecord: !item.isRecord,
            loading: false
        };
        console.log('==========================>', newFormList);
        proxyOnChange(newFormList);
        forceFormCheck();
        if (itemIsRecording) {
            // 如果调用时正在录制问题录音，则上报服务器,这代表最终一次的上报
            console.log('录音片段上报服务器');
            allowEmptyAnswer();
            handleConfirm(`answer_${item.id || item.key}`, index, 'answer', 'answerContent');
            // if (autoSaveTimmer) clearInterval(autoSaveTimmer); // 清除定时上传的定时器
        } else {
            // 此时为首次启动上传，启动定时上传定时器
            // autoSaveTimmer = setInterval(() => {
            //     saveQuestionRecToServer(`answer_${item.id || item.key}`, index);
            // }, 5000);
        }
        return true;
    };

    const onDeleteRecordTime = (item, index, listIndex) => {
        if (item.isRecord) {
            message.error('请先停止当前录音');
            return;
        }
        allowEmptyAnswer();
        const newFormList = formList.slice();
        const { answer = {} } = newFormList[index];
        let { answerTimes = [] } = answer;
        answerTimes.splice(listIndex, 1);
        answerTimes = answerTimes.map((time, i) => ({
            ...time,
            sort: i + 1
        }));
        newFormList[index] = {
            ...newFormList[index],
            answer: {
                ...(newFormList[index].answer || {}),
                answerTimes
            }
        };
        proxyOnChange(newFormList);
        handleConfirm(`answer_${item.id || item.key}`, index, 'answer', 'answerContent');
    };

    // 录音按钮
    const renderRecordButton = (item, index) => {
        if (!item.isEqual || disableButton) {
            return null;
        }
        const { isQuestionEdit, loading: itemLoading, isRecord } = item || {};
        let classes = cn(styles.questionRecordButtonIconWrap, {
            [styles.unQuestionRecordBtnIcon]: isQuestionEdit
        });
        if (isRecord) {
            classes = styles.questionRecordButtonIconing;
        }
        return (
            <div style={{ display: 'inline-flex' }}>
                <RecordTagButton
                    params={{
                        item,
                        index,
                        classes,
                        isRecord,
                        onQuestionRecord,
                        loading: itemLoading
                    }}
                />
            </div>
        );
    };

    // 渲染自定义问题录音片段内容
    const renderRecordContent = useCallback(
        (item, index) => {
            const { answer } = item || {};
            if (!answer?.answerTimes?.length) {
                return null;
            }
            return answer.answerTimes.map((l, i) =>
                l.endTime ? (
                    <QuestionRecItem
                        key={l?.endTime}
                        {...{
                            l,
                            i,
                            item,
                            index,
                            onDeleteRecordTime,
                            durationMSRef,
                            recData,
                            mixedRecordAndUploadState
                        }}
                    />
                ) : (
                    <span />
                )
            );
        },
        [onDeleteRecordTime]
    );

    // 回答 头部
    const renderAnswerToolbar = useCallback(
        (item, index) => (
            // const { isEqual } = item;
            <div>
                <Toolbar>
                    <div style={{ flex: 1 }}>
                        <Label value="答复" />
                    </div>
                    {renderRecordButton(item, index)}
                </Toolbar>
                <div className={styles.questionRecordDateList}>{renderRecordContent(item, index)}</div>
            </div>
        ),
        [renderRecordButton, renderRecordContent]
    );

    // 回答 内容
    const renderAnswerContent = useCallback(
        (item, index) => {
            const type = 'answer';
            const contentName = `${type}Content`;
            const val = item?.[type]?.[contentName] ?? '';
            if (item?.isEqual) {
                return getFieldDecorator(`answer_${item.id || item.key}`, {
                    initialValue: val,
                    rules: answerRules
                })(
                    <LimitInput
                        inputRef={answerRef}
                        area
                        maxLength={2000}
                        placeholder="请输入"
                        autoSize={{ minRows: 4, maxRows: 4 }}
                        onBlur={() => {
                            if (val === getFieldValue(`answer_${item.id || item.key}`)) return;
                            handleConfirm(`${type}_${item.id || item.key}`, index, type, contentName);
                        }}
                    />
                );
            }
            return (
                <div className={styles.browsingContainer}>
                    {val.split('\n').map(show => (
                        <span key={show}>{show}</span>
                    ))}
                </div>
            );
        },
        [handleToggleEdit, answerRef]
    );

    // 回答: 包含音频片段 + 录音按钮 + 文字答复
    const renderAnswer = useCallback(
        (item, index) => {
            const { isEqual, answer } = item || {};
            if (!isEqual && !answer?.answerContent && !answer?.answerTimes?.length) {
                return null;
            }
            return (
                <Form.Item>
                    {renderAnswerToolbar(item, index)}
                    {isEqual || answer?.answerContent ? renderAnswerContent(item, index) : null}
                </Form.Item>
            );
        },
        [renderAnswerToolbar, renderAnswerContent]
    );

    // 评论 头部
    const renderCommentToolbar = useCallback(
        item => (
            <>
                <Toolbar>
                    <Row type="flex" style={{ flex: 1 }} align="middle">
                        <Label value="评价" item={item} />
                    </Row>
                </Toolbar>
            </>
        ),
        []
    );

    // 评论 内容
    const renderCommentContent = useCallback(
        (item, index) => {
            const type = 'comment';
            const contentName = `${type}Content`;
            const val = item?.[type]?.[contentName] ?? '';
            return getFieldDecorator(`comment_${item.id || item.key}`, {
                initialValue: val,
                rules: [
                    { required: item?.isEqual, message: '请输入评价!', whitespace: true },
                    { max: 1000, message: '评价不能超过1000个字符' }
                ]
            })(
                <LimitInput
                    inputRef={commentRef}
                    area
                    maxLength={1000}
                    autoSize={{ minRows: 4, maxRows: 4 }}
                    placeholder="请输入"
                    onBlur={() => {
                        if (val === getFieldValue(`${type}_${item.id || item.key}`)) return;
                        handleConfirm(`${type}_${item.id || item.key}`, index, type, contentName);
                    }}
                />
            );
        },
        [handleConfirm, handleToggleEdit, commentRef]
    );

    // 评论
    const renderComment = useCallback(
        (item, index) => (
            <Form.Item>
                {renderCommentToolbar(item, index)}
                {renderCommentContent(item, index)}
            </Form.Item>
        ),
        [renderCommentToolbar, renderCommentContent]
    );

    // 重新记录数组顺序
    const reorder = (list, startIndex, endIndex) => {
        const result = Array.from(list);

        const [removed] = result.splice(startIndex, 1);

        result.splice(endIndex, 0, removed);
        return result;
    };

    const onMoveEnd = async (startIndex, endIndex) => {
        const items = reorder(formList, startIndex, endIndex);
        try {
            setLoading(true);
            const { code } = await changeQuestionsOrder({
                srcQuestionId: formList[startIndex]?.id,
                destQuestionId: formList[endIndex]?.id
            });
            if (code === 10000) {
                onChange(items);
                sendEventToWS('question');
                broadcastUpdateMsg(true);
            }
            setLoading(false);
        } catch (e) {
            setLoading(false);
            console.log(e);
        }
    };

    const renderOperateBtn = (item, index) => {
        const { isEqual, isNew, question } = item;
        if (isEqual) {
            const selfFormList = formList.filter(v => v.isEqual);
            const isMove = selfFormList.every(v => !!v.question);
            const Com = [];
            if (isEqual || isNew) {
                Com.push(
                    <Popconfirm
                        key={question}
                        getPopupContainer={trigger => trigger.parentNode}
                        overlayClassName={styles.PopconfirmCustomer}
                        title={
                            <div className={styles.PopconfirmCustomerContent}>
                                <div className={styles.PopconfirmCustomerTitle}>确定删除此自定义问题？</div>
                                {question && <div className={styles.PopconfirmCustomerDec}>答复及评价将一并删除</div>}
                            </div>
                        }
                        onConfirm={() => {
                            onDeleteQuestion(index);
                        }}
                    >
                        <Icon title="删除" type="DeleteIcon" className={styles.deleteIcon} />
                    </Popconfirm>
                );
            }
            if (isMove) {
                if (index !== 0) {
                    Com.push(
                        <Icon
                            key={question}
                            title="上移"
                            type="TopArrowIcon"
                            onClick={() => {
                                onMoveEnd(index, index - 1);
                            }}
                        />
                    );
                }
                if (index !== selfFormList.length - 1) {
                    Com.push(
                        <Icon
                            key={question}
                            title="下移"
                            type="DownArrowIcon"
                            onClick={() => {
                                onMoveEnd(index, index + 1);
                            }}
                        />
                    );
                }
            }
            return (
                <DividerContainer
                    className={styles.questionBtnWrap}
                    type="horizontal"
                    dividerProps={{ style: { margin: '16px auto', minWidth: 12, width: 12 } }}
                >
                    {Com}
                </DividerContainer>
            );
        }
        return null;
    };

    return (
        <Spin spinning={loading}>
            {formList.map((item, index) => (
                <div className={cn(styles.interviewQuestionFormItem, '.question-item')} key={item.id || item.key}>
                    <div className={styles.questionWrap}>
                        <div className={styles.questionInfo}>
                            <div className={styles.questionHeader}>
                                {renderTitle(item, index)}
                                {/* <span className={styles.questionHeaderContent}></span> */}
                            </div>
                            <div className={styles.questionContent}>
                                {renderAnswer(item, index)}
                                {renderComment(item, index)}
                                <div
                                    className={cn({
                                        [styles.questionContentModal]: item[editFlagName('question')]
                                    })}
                                />
                            </div>
                        </div>
                        {renderOperateBtn(item, index)}
                    </div>
                    <Form.Item>
                        {getFieldDecorator(`interviewQuestion[${index}].submitCheck`, {
                            validateTrigger: 'onSubmit', // 设置进行表单验证的时机为onSubmit
                            force: true,
                            rules: [
                                {
                                    validator(_, interviewQuestion, callback) {
                                        const formItem = getFieldValue('interviewQuestions')?.[index];
                                        if (
                                            formItem?.[editFlagName('question')] ||
                                            formItem?.[editFlagName('answer')] ||
                                            formItem?.[editFlagName('comment')]
                                        ) {
                                            callback('请完成自定义问题编辑');
                                            return;
                                        }
                                        if (formItem?.isRecord) {
                                            callback('当前录音正在执行！');
                                            return;
                                        }
                                        callback();
                                    }
                                }
                            ]
                        })(<div />)}
                    </Form.Item>
                </div>
            ))}
            <div className={cn(styles.addQuestion, allowAdd ? '' : styles.addBtnGray)} onClick={onAddQuestion}>
                + 添加问题
            </div>
        </Spin>
    );
};
export default memo(Question);
